﻿@using BlazorDatasheet.Edit
@using BlazorDatasheet.Util;
@using System.Linq;
@using BlazorDatasheet.Core.Data
@using BlazorDatasheet.Core.Edit
@using BlazorDatasheet.Core.Interfaces
@using BlazorDatasheet.Core.Util

@typeparam TEnum where TEnum : Enum

@inherits BaseEditor

<input @bind="CurrentValue"
       class="text-input"
       disabled
       style="@CssUtil.GetStyledInput(Cell)"
       @ref="InputRef"/>

<div class="select-list">
    @foreach (TEnum val in Items)
    {
        <div class="select-item @(val.Equals(currentSelected) ? "active" : "")"
             @onmouseup="() => selectItem(val)">
            @val.ToString()
        </div>
    }
</div>


@code {

    private IReadOnlyCell Cell;
    TEnum? currentSelected;
    IList<TEnum> Items = Enum.GetValues(typeof(TEnum)).Cast<TEnum>().ToList();

    public override void BeforeEdit(IReadOnlyCell cell, Sheet sheet)
    {
        Cell = cell;
    }

    public override void BeginEdit(EditEntryMode entryMode, string? editValue, string key)
    {
        try
        {
            if (editValue == null)
            {
                CurrentValue = default(TEnum).ToString();
                return;
            }

            var cellValue = (TEnum)Enum.Parse(typeof(TEnum), editValue!.ToString());
            CurrentValue = cellValue.ToString();

            if (entryMode == EditEntryMode.Key && !String.IsNullOrEmpty(key) && key.Length == 1)
            {
                var stringValue = key.ToUpperInvariant();
                var currenEnum = Items
                    .FirstOrDefault(x => x.ToString().ToUpperInvariant().StartsWith(stringValue));
                CurrentValue = currenEnum.ToString();
            }
        }
        catch (Exception e)
        {
            CurrentValue = default(TEnum).ToString();
        }
    }

    public override bool HandleKey(string key, bool ctrlKey, bool shiftKey, bool altKey, bool metaKey)
    {
        if (KeyUtil.IsEnter(key))
        {
            if (currentSelected is not null)
            {
                selectItem(currentSelected);
            }
            else
            {
                return true;
            }
        }

        if (KeyUtil.IsKeyDown(key))
        {
            hoverItem(1);
            return true;
        }

        if (KeyUtil.IsKeyUp(key))
        {
            hoverItem(-1);
            return true;
        }

        return base.HandleKey(key, ctrlKey, shiftKey, altKey, metaKey);
    }

    void hoverItem(int direction)
    {
        var index = currentSelected is not null ? Items.IndexOf(currentSelected) : 0;

        index = direction > 0 ? Math.Min(index + 1, Items.Count - 1) : Math.Max(index - 1, 0);

        currentSelected = Items[index];

        StateHasChanged();
    }

    void selectItem(TEnum item)
    {
        CurrentValue = item.ToString();
        AcceptEdit();
    }

}